/*!
  \file
  Header file for a buffer object using cudaHostAlloc
*/

#ifndef SCIGPU_HHV_CUDA_PINNED_BUFFER_HPP
#define SCIGPU_HHV_CUDA_PINNED_BUFFER_HPP

#include <vector>

#include "cudahostallocator.hpp"

namespace SciGPU {
  namespace HHV {

    //! Templated buffer with pinned memory
    /*!
      This buffer type makes use of the
      SciGPU::HHV::cuda_host_allocator allocator in its
      internal \c std::vector buffer.
      This ensures that the memory on the host is pinned,
      enabling faster transfers to and from the GPU.
      @tparam T     The type of data stored in the buffer
      @tparam flags The flags passed to \c cudaHostAlloc
    */
    template<typename T, unsigned int flags=cudaHostAllocDefault>
    class CUDAhostBuffer : public BufferObject<T> {
    public:
      //! Constructor
      CUDAhostBuffer( void ) : BufferObject<T>(),
                               buffer() {};

      //! Destructor
      ~CUDAhostBuffer( void ) {};

      //! Clone
      virtual BufferObject<T>* clone( void ) const {
        return( new CUDAhostBuffer<T> );
      }

      //! Allocation of a pinned host buffer
      virtual void Allocate( const size_t nItems ) {
        this->buffer.resize( nItems );
      }

      //! Release of the pinned host buffer
      virtual void Release( void ) {
        this->buffer.clear();
      }

      //! Accessor for first element
      virtual T* start( void ) {
        return( &(this->buffer.at(0)) );
      }

    private:
      //! Internal pinned memory buffer
      std::vector<T, cuda_host_allocator<T,flags> > buffer;
    };

  }
}


#endif
